/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_adapter_manager.h"
#include "sle_hilog.h"

namespace OHOS {
namespace NearLink {
namespace SleStandard {
SleAdapterManager::SleAdapterManageImpl::SleAdapterManageImpl()
{
    callbackImpl_ = std::make_unique<AdapterCallbackImplement>(*this);
    SLE_ASSERT_AND_RETURN_LOG(callbackImpl_, "callbackImpl null error!");
    SleErrorCode ret = SleHostService::GetInstance()->RegisterHostCallback(*callbackImpl_.get());
    SLE_ASSERT_AND_RETURN_LOG(ret == SLE_NO_ERROR, "register host callback failed!");
}

SleAdapterManager::SleAdapterManageImpl::~SleAdapterManageImpl()
{
    SLE_ASSERT_AND_RETURN_LOG(callbackImpl_, "callbackImpl null error!");
    SleErrorCode ret = SleHostService::GetInstance()->UnregisterHostCallback(*callbackImpl_.get());
    SLE_ASSERT_AND_RETURN_LOG(ret == SLE_NO_ERROR, "unregister host callback failed!");
}

void SleAdapterManager::SleAdapterManageImpl::EnableComming(SleErrorCode errCode)
{
    Message msg(SleAdapterStateMessage::MSG_ADAPTER_ENABLE_CMP, errCode == SLE_NO_ERROR ? true : false);
    SLE_ASSERT_AND_RETURN_LOG(stateMachine_, "state machine null error!");
    stateMachine_->ProcessMessage(msg);
}

void SleAdapterManager::SleAdapterManageImpl::DisableComming(SleErrorCode errCode)
{
    Message msg(SleAdapterStateMessage::MSG_ADAPTER_DISABLE_CMP, errCode == SLE_NO_ERROR ? true : false);
    SLE_ASSERT_AND_RETURN_LOG(stateMachine_, "state machine null error!");
    stateMachine_->ProcessMessage(msg);
}

void SleAdapterManager::SleAdapterManageImpl::OnSleStateChange(const SleDeviceState state)
{
    state_ = state;
    callbacks_.ForEach([state](ISleAdapterManagerCallback &callback) {
        callback.OnSleStateChange(state);
    });
}

// SleAdapterManager
SleAdapterManager::SleAdapterManager()
{
    SLE_LOGD("SleAdapterManager In");
    pimpl_ = std::make_unique<SleAdapterManageImpl>();
    SLE_ASSERT_AND_RETURN_LOG(pimpl_, "pimpl null error!");
}

SleAdapterManager::~SleAdapterManager() {}

SleAdapterManager *SleAdapterManager::GetInstance()
{
    static SleAdapterManager instance;
    return &instance;
}

SleErrorCode SleAdapterManager::Start() const
{
    SLE_LOGD("Start In");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    pimpl_->stateMachine_ = std::make_unique<SleAdapterStateMachine>();
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_->stateMachine_, SLE_ERR_NOT_READY, "state machine ptr error!");
    SleErrorCode ret = pimpl_->stateMachine_->Initialize();
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, ret, "init state machine failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleAdapterManager::Enable() const
{
    //预留验证 Permission
    int32_t state;
    SleErrorCode ret = GetState(state);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, ret, "get sle state failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(
        state != SLE_HOST_STATE_ENABLED, SLE_ERR_ENABLE_SUCCESS_WHEN_ENABLED, "sle already enable error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(state == SLE_HOST_STATE_DISABLED, SLE_ERR_STATUS_WRONG, "current sle state error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_->stateMachine_, SLE_ERR_NOT_READY, "sle state machine null error!");
    Message msg(SleAdapterStateMessage::MSG_ADAPTER_ENABLE_REQ);
    bool result = pimpl_->stateMachine_->ProcessMessage(msg);
    SLE_ASSERT_AND_RETURN_RET_LOG(result, SLE_ERR_FAILED, "enable sle failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleAdapterManager::Disable() const
{
    //预留验证 Permission
    int32_t state;
    SleErrorCode ret = GetState(state);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, ret, "get sle state failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(
        state != SLE_HOST_STATE_DISABLED, SLE_ERR_DISABLE_SUCCESS_WHEN_DISABLED, "sle already disable error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(state == SLE_HOST_STATE_ENABLED, SLE_ERR_STATUS_WRONG, "current sle state error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_->stateMachine_, SLE_ERR_NOT_READY, "sle state machine null error!");
    Message msg(SleAdapterStateMessage::MSG_ADAPTER_DISABLE_REQ);
    bool result = pimpl_->stateMachine_->ProcessMessage(msg);
    SLE_ASSERT_AND_RETURN_RET_LOG(result, SLE_ERR_FAILED, "disable sle failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleAdapterManager::GetState(int32_t &state) const
{
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    state = pimpl_->state_;
    return SLE_NO_ERROR;
}

SleErrorCode SleAdapterManager::RegisterAdapterCallback(ISleAdapterManagerCallback &callback) const
{
    SLE_LOGD("RegisterAdapterCallback In");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(
        pimpl_->callbacks_.Register(callback), SLE_ERR_FAILED, "register adapter callback failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleAdapterManager::UnregisterAdapterCallback(ISleAdapterManagerCallback &callback) const
{
    SLE_LOGD("UnregisterAdapterCallback In");
    SLE_ASSERT_AND_RETURN_RET_LOG(pimpl_, SLE_ERR_NOT_READY, "pimpl null error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(
        pimpl_->callbacks_.Unregister(callback), SLE_ERR_FAILED, "unregister adapter callback failed!");
    return SLE_NO_ERROR;
}

void SleAdapterManager::OnSleStateChange(const SleDeviceState state) const
{
    SLE_ASSERT_AND_RETURN_LOG(pimpl_, "pimpl null error!");
    pimpl_->OnSleStateChange(state);
}
} // SleStandard
} // NearLink
} // OHOS